/*
IIC通信协议
1、（在发送、接收数据的时候）当SCL为高电平时，SDA线不允许变化；当SCL线为低电平时，SDA线可以任意0、1变化。 
2、（在任意时候）只有当SCL为高电平时，IIC电路才对SDA线上的电平（0或者1）进行记录，当SCL线为低电平时，无论SDA是高还是低，IIC电路都不对SDA进行采样。

空闲状态
所有器件释放总线，由两条信号线各自的上拉电阻把电平拉高。

开始信号：当SCL为高期间，SDA由高到低的跳变；启动信号是一种电平跳变时序信号，而不是一个电平。
停止信号：当SCL为高期间，SDA由低到高的跳变；停止信号也是一种电平跳变时序信号，而不是一个电平信号。
应答信号：发送器每发送一个字节，就在时钟脉冲9期间释放数据先，由接收器反馈一个应答信号。
	应答信号为低电平时，规定为有效应答位(ACK简称应答位)，表示接收器已经成功接收了该字节；
	应答信号为高电平时，规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
	对于反馈有效应答位ACK的要求是，接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低，并且确保在该时钟的高电平期间位稳定的低电平。
	如果接收器是主控器，则在它收到最后一个字节后，发送一个NACK信号，以通知被控发送器结束数据发送，并释放SDA线，以便主控接收器发送一个停止信号P。
发送数据：在I2C总线上传送的每位数据都有一个时钟脉冲相对应（或同步控制），即在SCL串行时钟的配合下，SDA逐位地串行传送每一位数据。数据位的传输是边沿触发。
接收数据：发送一位一位发，接收一位一位接
单片机发送完一个字节后面必须跟一个等待应答函数
*/

#include "i2cDrive.h"
#include "delay.h"

//io口模拟i2c驱动
//共7个操作IO函数和1个延时需要实现

static void i2c_Delay(void){		//微秒级延时，一般5-10us
	delay_us(5);
}

void i2c_Start(mI2CTypedef_t *i2c){
	i2c->IIC_SDA_H();
	i2c_Delay();
	i2c->IIC_SCL_H();
	i2c_Delay();
	i2c->IIC_SDA_L();
	i2c_Delay();
	i2c->IIC_SCL_L();
#if I2C_FAST == 0
	i2c_Delay();
#endif
}

void i2c_Stop(mI2CTypedef_t *i2c){
	i2c->IIC_SDA_L();
	i2c_Delay();
	i2c->IIC_SCL_H();
	i2c_Delay();
	i2c->IIC_SDA_H();
	i2c_Delay();					//这个delay不必要，不过加上波形更清晰
}

void i2c_SendByte(mI2CTypedef_t *i2c,u8 _ucByte){
	u8 i;
	/*first bit7 */
	for(i=0;i<8;i++){
		if(_ucByte & 0x80){
			i2c->IIC_SDA_H();
		}
		else{
			i2c->IIC_SDA_L();
		}
		i2c_Delay();
		i2c->IIC_SCL_H();
		i2c_Delay();
		i2c->IIC_SCL_L();   
#if I2C_FAST == 0   
		i2c_Delay();
#endif
		_ucByte <<= 1; 
	}
#if I2C_FAST == 0
	i2c->IIC_SDA_H(); 	//完事了释放SDA总线
	i2c_Delay();
#endif	
}

u8 i2c_ReadByte(mI2CTypedef_t *i2c){
	u8 i;
	u8 value;
	/*first bit7 */
	value = 0;
#if I2C_FAST == 0
	i2c->IIC_SDA_H();		//读之前肯定是wack，里面已经释放了sda
	i2c_Delay();
#endif	
	for(i=0;i<8;i++){
		value <<= 1;
		i2c_Delay();		//允许从机修改sda时间
		i2c->IIC_SCL_H();	//锁定sda
		if(i2c->IIC_READ_SDA()){
			value++;
		}
		i2c_Delay();
		i2c->IIC_SCL_L();
#if I2C_FAST == 0
		i2c_Delay();
#endif	
	}
	return value;
}

u8 i2c_WaitAck(mI2CTypedef_t *i2c){
	u8 re;
	u8 count=2;
	i2c->IIC_SDA_H();
	i2c_Delay();
	i2c->IIC_SCL_H();
	i2c_Delay();
	do{
		count--;
		if (i2c->IIC_READ_SDA()){
			re = 1;
		}
		else{
			re = 0;
			break;
		}
		i2c_Delay();
	}while(count>0);
	i2c->IIC_SCL_L();
#if I2C_FAST == 0
	i2c_Delay();
#endif		
	return re;
}

void i2c_Ack(mI2CTypedef_t *i2c){
	i2c->IIC_SDA_L();
	i2c_Delay();
	i2c->IIC_SCL_H();
	i2c_Delay();
	i2c->IIC_SCL_L();
#if I2C_FAST == 0
	i2c_Delay();
#endif
	i2c->IIC_SDA_H();
}

void i2c_NAck(mI2CTypedef_t *i2c){
	i2c->IIC_SDA_H();
	i2c_Delay();
	i2c->IIC_SCL_H();
	i2c_Delay();
	i2c->IIC_SCL_L();
#if I2C_FAST == 0
	i2c_Delay();
#endif
}

u8 i2c_CheckDevice(mI2CTypedef_t *i2c,u8 _Address){
	u8 ucAck;
	if(i2c->IIC_READ_SDA()&&i2c->IIC_READ_SCL()){
		i2c_Start( i2c );                        
		i2c_SendByte( i2c, _Address | I2C_WR);
		ucAck = i2c_WaitAck( i2c );
		i2c_Stop( i2c );
		return ucAck;
	}
	return 1;
}

void i2c_SdaErrorClear(mI2CTypedef_t *i2c){		//清除SDA总线挂死
	u8 i;
	for(i=0;i<9;i++){
		i2c->IIC_SCL_L();
		i2c_Delay();
		if(i2c->IIC_READ_SDA()){
			break;
		}
		i2c->IIC_SCL_H();
	}
	i2c_Delay();
	i2c_Stop(i2c);
}


/************************   应用程序开头实例   ***********************/

#define NPA_ADDR 	0xDA		//设备iic地址，如果手册提供的是七位设备地址，需左移一位 (0x6D<<1)

mI2CTypedef_t NPAI2c;			//io模拟i2c接口

static void i2c_SdaH(void){
	
}

static void i2c_SdaL(void){
	
}

static void i2c_SclH(void){
	
}

static void i2c_SclL(void){
	
}

static u8 i2c_ReadSda(void){
	return 0;
}

static u8 i2c_ReadScl(void){
	return 0;
}

void npa_i2c_init(mI2CTypedef_t *i2c){
	i2c->IIC_InitPort=0;
	i2c->IIC_SDA_H=i2c_SdaH;
	i2c->IIC_SDA_L=i2c_SdaL;
	i2c->IIC_SCL_H=i2c_SclH;
	i2c->IIC_SCL_L=i2c_SclL;
	i2c->IIC_READ_SDA=i2c_ReadSda;
	i2c->IIC_READ_SCL=i2c_ReadScl;
}

//从uWriteAddress地址开始写入len字节数据					//通常情况下可以这样读写，但是顶不住有些设备与众不同，所以具体读写时序还要看芯片手册
void sd_i2c_write(u8 uWriteAddress,u8 *buf,u8 len)
{
	i2c_Start(&NPAI2c);
	i2c_SendByte(&NPAI2c,NPA_ADDR|I2C_WR);
	i2c_WaitAck(&NPAI2c);
	i2c_SendByte(&NPAI2c,(uWriteAddress) & 0xFF);
	i2c_WaitAck(&NPAI2c);
	while(len--){
		i2c_SendByte(&NPAI2c,*buf++);
		i2c_WaitAck(&NPAI2c);
	}
	i2c_Stop(&NPAI2c);
}
//从uWriteAddress地址开始读出len字节数据
u8 sd_i2c_read(u8 uReadAddress,u8 *buf,u8 len)
{
	i2c_Start(&NPAI2c);
	i2c_SendByte(&NPAI2c,NPA_ADDR|I2C_WR);
	if(1==i2c_WaitAck(&NPAI2c)){	//ERROR
		goto ERR;
	}
	i2c_SendByte(&NPAI2c,uReadAddress);
	if(1==i2c_WaitAck(&NPAI2c)){	//ERROR
		goto ERR;
	}
	i2c_Start(&NPAI2c);
	i2c_SendByte(&NPAI2c,NPA_ADDR|I2C_RD);
	if(1==i2c_WaitAck(&NPAI2c)){	//ERROR
		goto ERR;
	}
	while(len-->1){
		*buf++ = i2c_ReadByte(&NPAI2c);
		i2c_Ack(&NPAI2c);
	}
	*buf++ = i2c_ReadByte(&NPAI2c);
	i2c_NAck(&NPAI2c);
	i2c_Stop(&NPAI2c);
	return 1;//正常返回
ERR:
	i2c_SdaErrorClear(&NPAI2c);
	return 0;	
}
